package wator.model;

/**
 * A topology in our terms defines the size of the universe (the size vector)
 * and how the "ends" of these universe are "connected" in each dimension. 
 * Only position vectors of individuals, which are between the 0-vector and 
 * <code>sizeVector</code> (element-wise) are allowed. What to do when a 
 * position vector exceeds these ranges are up to implementing subclasses. A
 * simple topology (also used in the initial wator paper) would be a torus, but
 * other topologies are possible. Note that implementing subclasses should not
 * make assumptions about the dimension of the vector space, but use vector
 * operations defined by <code>IntegerVector</code>.
 * 
 * @see IntegerVector
 */
abstract public class Topology {
	
	/**
	 * The size vector of the universe. Only position vectors of individuals 
	 * which are between the 0-vector and <code>sizeVector</code>
	 * (element-wise) are allowed.
	 */
	protected IntegerVector sizeVector = null;
	
	/**
	 * Set the size vector of this topology.
	 * 
	 * @param sizeVector the new size vector
	 */
	public void setSizeVector(IntegerVector sizeVector) {
		this.sizeVector = sizeVector;
	}
	
	/**
	 * Get the current size vector of this topology.
	 * 
	 * @return the current size vector
	 */
	public IntegerVector getSizeVector() {
		return sizeVector;
	}
	
	/**
	 * Translate a vector into the feasible range. If this is not
	 * possible, return <code>null</code>.
	 * 
	 * @param v the vector which should be checked/translated
	 * @return A vector in the feasible range or <code>null</code>
	 * @throws NullPointerException if the current size vector or
	 * 				<code>v</code> is null
	 */
	abstract public IntegerVector apply(IntegerVector v);
	
	/**
	 * Get the shortest connecting vector between <code>v1</code> and 
	 * <code>v2</code>. This might be simply v2-v1. However, if the shortest
	 * connecting vector cross universe borders, more sophisticated analysis  
	 * has to be done such as vector reduction.
	 * 
	 * @param v1 the first vector
	 * @param v2 the second vector
	 * @return the shortest vector v_d for which holds v1+v_d=v2 in the 
	 * 				given topology 
	 * @throws ClassCastException if v1 and v2 do not have the same dimension
	 * @throws NullPointerException if one of the arguments is null
	 * @see wator.model.IntegerVector#euclideanDistance(IntegerVector)
	 * @see wator.model.IntegerVector#reduce(IntegerVector)
	 */
	abstract public IntegerVector distanceVector
			(IntegerVector v1, IntegerVector v2);
}
